package org.sibframework.utils;

import java.util.ArrayList;
import java.util.List;

/**
 * @author song.chinamedcom.com
 *
 */
public class TraceTool {

	
	/**
	 * 跟踪当前代码的调用顺序。
	 * @return 整个调用链的数组。
	 */
	public List<String> trace() {
		List<String> result = new ArrayList<String>();

		for (StackTraceElement element : Thread.currentThread().getStackTrace()) {
			
			if (element.getClassName().equals("org.sibframework.utils.TraceTool")) {
				continue;
			}
			result.add(element.toString());
		}

		return result;
	}

	/**
	 * 定位当前代码的位置，类名，方法名，行数。
	 * @return 返回类名，方法名，行数。类似：org.sibframework.sda.SimpleDataAccess.query(SimpleDataAccess.java:2535)
	 */
	public String locate() {
		return this.locate(null);
	}

	
	/**
	 * 定位当前代码的位置，类名，方法名，行数。忽略给定的对象的类，返回对该对象的调用的位置
	 * @param obj 忽略的对象。
	 * @return  返回类名，方法名，行数。类似：org.sibframework.sda.SimpleDataAccess.query(SimpleDataAccess.java:2535)
	 */
	public String locate(Object obj) {
		return this.locate(obj.getClass());
	}
	
	/**
	 * 定位当前代码的位置，类名，方法名，行数。忽略给定的类，返回对该类对象的调用的位置。
	 * @param exclude 忽略的类。
	 * @return  返回类名，方法名，行数。类似：org.sibframework.sda.SimpleDataAccess.query(SimpleDataAccess.java:2535)
	 */
	public String locate(Class<?> exclude) {
		String result = null;
			
		for (StackTraceElement element : Thread.currentThread().getStackTrace()) {
			
			try {
				//跳过自己
				if (element.getClassName().equals(Thread.class.getName())) {
					continue;
				}
				if (element.getClassName().equals(this.getClass().getName())) {
					continue;
				}

				if (element.getClassName().startsWith("org.sibframework.sda.")) {
					result = element.toString();
					continue;
				}
				
				//跳过排除的类
				if (exclude != null) {
					if (element.getClassName().equals(exclude.getName())) {
						result = element.toString();
						continue;
					}
				}
				
				//返回位置
				result = element.toString();					
				return result;
				
			} catch (Exception e1) {
				e1.printStackTrace();
				result = e1.getLocalizedMessage();
			}
		}
		
		
		System.out.println("Can't trace a class, info:" + result);
		Thread.dumpStack();
	
		
		return "-unknown- ";
	}
	
	
	public static void main(String... args) {
		Describer.describe(new TraceTool().trace());
	}
	
}
